import type { ComputedRef, Ref } from 'vue'
import { computed, getCurrentInstance, shallowReactive, unref, watch } from 'vue'
import { useDebounceFn } from '@vueuse/core'
import type { ColEx } from '../types'
import type { AdvanceState } from '../types/hooks'
import type { FormProps, FormSchemaInner as FormSchema } from '../types/form'
import { isBoolean, isFunction, isNumber, isObject } from '@/utils/is'
import { useBreakpoint } from '@/hooks/event/useBreakpoint'

const BASIC_COL_LEN = 24

interface UseAdvancedContext {
  advanceState: AdvanceState
  emit: EmitType
  getProps: ComputedRef<FormProps>
  getSchema: ComputedRef<FormSchema[]>
  formModel: Recordable
  defaultValueRef: Ref<Recordable>
}

export default function ({ advanceState, emit, getProps, getSchema, formModel, defaultValueRef }: UseAdvancedContext) {
  const vm = getCurrentInstance()

  const { realWidthRef, screenEnum, screenRef } = useBreakpoint()

  const getEmptySpan = computed((): number => {
    if (!advanceState.isAdvanced)
      return 0

    // For some special cases, you need to manually specify additional blank lines
    const emptySpan = unref(getProps).emptySpan || 0

    if (isNumber(emptySpan))
      return emptySpan

    if (isObject(emptySpan)) {
      const { span = 0 } = emptySpan
      const screen = unref(screenRef) as string

      const screenSpan = (emptySpan as any)[screen.toLowerCase()]
      return screenSpan || span || 0
    }
    return 0
  })

  const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30)

  watch(
    [() => unref(getSchema), () => advanceState.isAdvanced, () => unref(realWidthRef)],
    () => {
      const { showAdvancedButton } = unref(getProps)
      if (showAdvancedButton)
        debounceUpdateAdvanced()
    },
    { immediate: true },
  )

  function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) {
    const width = unref(realWidthRef)

    const mdWidth
      = Number.parseInt(itemCol.md as string)
      || Number.parseInt(itemCol.xs as string)
      || Number.parseInt(itemCol.sm as string)
      || (itemCol.span as number)
      || BASIC_COL_LEN

    const lgWidth = Number.parseInt(itemCol.lg as string) || mdWidth
    const xlWidth = Number.parseInt(itemCol.xl as string) || lgWidth
    const xxlWidth = Number.parseInt(itemCol.xxl as string) || xlWidth
    if (width <= screenEnum.LG)
      itemColSum += mdWidth

    else if (width < screenEnum.XL)
      itemColSum += lgWidth

    else if (width < screenEnum.XXL)
      itemColSum += xlWidth

    else
      itemColSum += xxlWidth

    if (isLastAction) {
      advanceState.hideAdvanceBtn = false
      if (itemColSum <= BASIC_COL_LEN * 2) {
        // When less than or equal to 2 lines, the collapse and expand buttons are not displayed
        advanceState.hideAdvanceBtn = true
        advanceState.isAdvanced = true
      }
      else if (
        itemColSum > BASIC_COL_LEN * 2
        && itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)
      ) {
        advanceState.hideAdvanceBtn = false

        // More than 3 lines collapsed by default
      }
      else if (!advanceState.isLoad) {
        advanceState.isLoad = true
        advanceState.isAdvanced = !advanceState.isAdvanced
      }
      return { isAdvanced: advanceState.isAdvanced, itemColSum }
    }
    if (itemColSum > BASIC_COL_LEN * (unref(getProps).alwaysShowLines || 1)) {
      return { isAdvanced: advanceState.isAdvanced, itemColSum }
    }
    else {
      // The first line is always displayed
      return { isAdvanced: true, itemColSum }
    }
  }

  const fieldsIsAdvancedMap = shallowReactive({})

  function updateAdvanced() {
    let itemColSum = 0
    let realItemColSum = 0
    const { baseColProps = {} } = unref(getProps)

    for (const schema of unref(getSchema)) {
      const { show, colProps } = schema
      let isShow = true

      if (isBoolean(show))
        isShow = show

      if (isFunction(show)) {
        isShow = show({
          schema,
          model: formModel,
          field: schema.field,
          values: {
            ...unref(defaultValueRef),
            ...formModel,
          },
        })
      }

      if (isShow && (colProps || baseColProps)) {
        const { itemColSum: sum, isAdvanced } = getAdvanced(
          { ...baseColProps, ...colProps },
          itemColSum,
        )

        itemColSum = sum || 0
        if (isAdvanced)
          realItemColSum = itemColSum

        fieldsIsAdvancedMap[schema.field] = isAdvanced
      }
    }

    // 确保页面发送更新
    vm?.proxy?.$forceUpdate()

    advanceState.actionSpan = (realItemColSum % BASIC_COL_LEN) + unref(getEmptySpan)

    getAdvanced(unref(getProps).actionColOptions || { span: BASIC_COL_LEN }, itemColSum, true)

    emit('advanced-change')
  }

  function handleToggleAdvanced() {
    advanceState.isAdvanced = !advanceState.isAdvanced
  }

  return { handleToggleAdvanced, fieldsIsAdvancedMap }
}
